// CacheHash.h
//
// A hashtable especially designed to be used as a cache.
//
#ifndef __CACHEHASH_H
#define __CACHEHASH_H

#include <math.h>

#include "base/Processor.h"
#include "base/simconstants.h"
#include "base/simtypes.h"
#include "mem/CacheEntry.h"
#include "mem/LineFlags.h"
#include "util/HashTable.h"
#include "util/Logger.h"

struct CHAvailable {
    uint associativity;
    uint victimCache;
};

class CacheHash : public HashTable<VA, CacheEntry*> {
  public:
    NEW_DELETE_OPERATORS_H(CacheHash,__quote__(HashTable<VA,CacheEntry*>));

    CacheHash(Entity* owner, 
              Logger* logger,
              int size, 
              uint block_size, 
              uint assoc, 
              uint vcsize);
    virtual ~CacheHash();

    virtual unsigned int        hash (VA addr) const;
    virtual List<CacheEntry*>*  retrieve (VA addr) const;
    virtual List<CacheEntry*>*  retrieveSet (VA addr) const;
    virtual struct CHAvailable  spaceAvailable (VA addr) const;
    virtual void                insert (VA addr, CacheEntry* data);
    virtual void                remove (CacheEntry* ce);
    virtual bool                contains (VA addr) const;
    void    reserveVC();

    virtual void                clear ();

    // list is an in and out variable: remove items from it and
    // they will be removed from the cachehash after this function
    // returns. keep them sorted by the CacheEntryLessThan struct.
    //
    void visitSet (void (*vistor)(List<CacheEntry*>*, void*), void*);

    void remove (VA addr,
                 HashTableNode<VA, CacheEntry*>** walk,
                 HashTableNode<VA, CacheEntry*>** prev);
    Logger* getLogger () {
        return log;
    }
    Entity* getOwner () {
        return owner;
    }

 protected:
    Entity* owner;
    Logger* log;
    uint hashsize;
    uint size;
    uint assoc;
    uint block_size;
    uint vc_size;

    uint index_shift;
    uint index_mask;

    int* assocCounts;

    // Called when removing without a call to remove().  This can
    // happen during removal from a visitor and during a clear().
    void                        implicitRemoval (VA addr, CacheEntry* data);

    List<CacheEntry*> victimCache;
};

#endif // __CACHEHASH_H
